#ifndef TOKEN_H
#define TOKEN_H

#include "c_head.h"

#define SIZE_OF_TOKEN    5000				//Token数组的大小
#define SIZE_OF_KEYTAB   33
#define SIZE_OF_DELTAB   45
#define SIZE_OF_OTHERTAB 50

enum TokenType {  //类码对应值
    _keyword = 1, //关键字
    _identifier,  //标识符
    _delimiter,   //界符
    _constnum,    //算术常数
    _character,   //字符
    _string,      //字符串
    _notes,       //注释(不会出现在Token中)
    _space        //空白符(不会出现在Token中)
};
string typetoString(TokenType type);
class Token {		  //Token类
public:
    string name;
    TokenType type;   //类码
    int id;			  //对应符号表中的下标
    int row;          //该单词在源程序文件中的行数，用于检错时输出错误出现的行数
    Token() {
        row = 0;
        name = "";
    } 		    //无参构造方法
    Token(TokenType type, int id) { //有参构造方法
        this->type = type, this->id = id;
        this->row = 0;
        name ="";
    }
};
struct Domain { //域名类
    string id;       //域名
    int offset;        //偏移量
    int size;          //大小
    int typ;           //指向类型表下标
    Domain() {
        this->offset = 0;
        this->size = 0;
        this->typ = -1;
    }
};

struct RINFL {
    string structName;       //标识符源码
    string name;
    vector<Domain> memberName;      //成员名
    int typ;           //指向类型表下标
    int offset;        //偏移量
    int size;
    void* ptr;
};

struct AINFL {
    int low = 0;
    int up;
    int typ;           //指向类型表下标
    int len;
    int offset;
    string name;
};

// class SymbolTable {   //符号表总表类（标识符表）
// public:
//     enum Category {
//         _function = 1, //函数类型
//         _constant,	   //常量类型
//         _type,		   //类型类型
//         _variable,     //变量类型
//         _vn,           //换名形参
//         _vf,           //赋值形参
//         _domain        //域名类型
//     };
//     string name;       //标识符源码
//     int typ;           //指向类型表下标
//     //Category cat;	   //种类编码
//     int offset;        //偏移量
//     int prelev;        //前一级符号表
//     string domainName; //域名
//     SymbolTable() {
//         this->offset = 0;
//         this->prelev = -1;
//     }
// };
class SymbolTable {   //符号表总表类（标识符表）
public:
    enum Category {
        _function = 1, //函数类型
        _constant,	   //常量类型
        _type,		   //类型类型
        _domain,       //域名类型
        _variable,     //变量类型
        _vn,           //换名形参
        _vf,           //赋值形参
    };
    string name;       //标识符源码
    int typ;           //指向类型表下标
    Category cat;	   //种类编码
    int offset;        //偏移量
    int prelev;        //前一级符号表
    string domainName; //域名
    SymbolTable() {
        this->offset = 0; ;
        this->prelev = -1;
    }
};
// struct TypeTable {	   //类型表类
//     enum VarType {	   //变量类型
//         _int,          //整型
//         _float,		   //浮点型
//         _double,	   //双精度
//         _long,		   //长
//         _short,        //短
//         _char,		   //字符型
//         _void,         //空类型
//     };
//     VarType Tval;      //类码（类型编码）
//     int Tpoint;        //基本变量类型指向空（-1），还指向数组表
// };
struct TypeTable {	   //类型表类
    enum VarType {	   //变量类型
        _int,          //整型
        _float,		   //浮点型
        _double,	   //双精度
        _long,		   //长
        _short,        //短
        _char,		   //字符型
        _struct,      //空类型
        _string,       //字符串类型
        _array,        //数组类型
        _void,         //结构体类型
        _enum,         //枚举类型
        _union,        //联合类型
        _pointer,      //指针类型
        _function,     //函数类型
    };
    VarType Tval;      //类码（类型编码）
    int Tpoint;        //基本变量类型指向空（-1），还指向数组表1,指向结构体表2，指向函数表3
};

class Lex {		//语法分析，包含各种符号表
public:
    struct re_table {
        re_table() {}
        /*     https://zh.wikipedia.org/wiki/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F
            正则表达式简记
            1. *？代表非贪婪模式 即尽可能少的匹配
                .代表匹配除"\n"之外的任意字符
                + 匹配次数>=1
                * 匹配次数>=0
                ? 匹配次数<=1
                {n,m}   至少匹配n次 之多匹配m次
            2. \ + 转移字符
                \w  任意字母、数字、下划线
                \s 表示任意空白符(tab也包含在内)    \S 匹配任意非空白字符
                \d 表示匹配单个数字字符，\D 表示非数字字符匹配
            3. | 表示或者
        */
        vector<pair<regex, TokenType>> table{
            make_pair(regex(R"QWERTY(//.*\n|/\*(.|[\r\n])*?\*/)QWERTY"), _notes), //匹配注释
            make_pair(regex("typedef|void|const|char|int|unsigned|signed|short|long|float|double|sizeof|struct|enum|union|if|else|do|for|while|return|switch|case|default|break|continue|static|include|define|pragma|goto|cin|cout"), _keyword),
            //make_pair(regex("[a-zA-Z_][0-9a-zA-Z_]*"), IDENTIFIER),
            make_pair(regex("[a-zA-Z_]\\w*"), _identifier),                  // 一个字母 + \w
            make_pair(regex("-?[0-9]+((\\.[0-9]+)([eE][-+]?[0-9]+)|(\\.[0-9]+)|([eE][-+]?[0-9]+))?[fF]?"), _constnum), //匹配浮点数
            make_pair(regex("-?(0|[1-9][0-9]*|0[xX][0-9a-fA-F]+|0[0-7]+)[uU]?[lL]{0,2}"), _constnum), //匹配整型数（含十进制、十六进制、八进制）
            make_pair(regex("\\+\\+|--|\\+=|-=|\\*=|/=|%=|<<=|>>=|\\|=|\\&=|\\^=|\\+|-|\\*|/|==|>>|<<|=|>=|>|<=|<|;|\\{|\\}|\\(|\\)|\\[|\\]|,|!|%|\\|\\||\\&\\&|\\||\\&|:|#|\\.|->|\\?|~|\\^"), _delimiter),
            make_pair(regex("['][\\s\\S^']'"), _character),                  // 匹配不了转义字符 可以为空？''
            make_pair(regex("\".*\""), _string),
            make_pair(regex("\\s+"), _space) //匹配空白符
        };
    };
    Token tokenSeq[SIZE_OF_TOKEN]; //开辟token序列
    int index_of_token = 0;
    int row;   //记录行数
    string keyword_table[SIZE_OF_KEYTAB] = {
        "typedef","void","const","char","int","unsigned","signed","short",
        "long","float","double","sizeof","struct","enum","union","if","else","do","for","while","return",
        "switch","case","default","break","continue","static","include","define","pragma","goto","cin","cout"}; //关键字表
    string delimiter_table[SIZE_OF_DELTAB] = {
        "++","--","+=","-=","*=", "/=","%=", "<<=", ">>=","|=","&=",
        "^=","+","-","*","/","==",">>","<<","=",">=",">","<=","<",";","{","}","(",")","[","]",",","!","%",
         "||","&&","|","&",":","#",".","->","?","~","^" }; //界符表
    SymbolTable identifier_table[SIZE_OF_OTHERTAB];
    int index_of_idtfer = 0;//标识符表
    string constant_table[SIZE_OF_OTHERTAB];
    int index_of_const = 0;//常数表
    string character_table[SIZE_OF_OTHERTAB];
    int index_of_char = 0;//字符表
    string string_table[SIZE_OF_OTHERTAB];
    int index_of_string = 0;//字符串表
    void generateToken(string const& str, int& position);
    void lexicalAnalysis(string Filestream);	//词法扫描器的入口，调用generateToken()函数，生成四元式
    pair<string, TokenType> NEXT(int pos_of_token);
    void showDelimiterTab(); //输出界符表
    void showKeywordTab();   //输出关键字表
};

#endif // TOKEN_H
